package com.xzp.bams.service;

import com.xzp.bams.dao.ArrayDao;
import com.xzp.bams.dao.FileDao;
import com.xzp.bams.dao.IDao;
import com.xzp.bams.dao.ListDao;
import com.xzp.bams.entity.*;
import com.xzp.bams.exception.*;
import com.xzp.bams.vo.RankVO;

import javax.swing.*;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;

/**
 * @TODO
 * @Author xu
 * 2025/3/7
 */
public class Bank {
    //private ArrayDao dao;
    // 解耦
    private IDao<Account, List<Account>> dao;
    private static Bank bank;

    private Bank() {
        dao = new FileDao(); //面向接口编程

    }

    public static Bank getInstance() {
        if (bank == null) {
            bank = new Bank();
        }
        return bank;
    }
    /**
     * copy register
     */
    public Account register(String password, String repassword, String name, String personID, String email, int type)
            throws RegisterException, TypeException, QueryException {
        if (password == null || repassword == null || password.equals("") || repassword.equals("")) {
            /*System.out.println("密码不能为空");
            return null;*/
            throw new QueryException("密码不能为空");
        }

        Account acc = null;
        if (password.equals(repassword)) {
            //获取ID
            Long id = dao.createId();
            if (id != -1L) {
                switch (type) {
                    case 0:
                        //储蓄账户  多态
                        acc = new SavingAccount(id, password, name, personID, email, 0.0);
                        break;
                    case 1:
                        //信用账户  多态
                        acc = new CreditAccount(id, password, name, personID, email, 0.0, 1500.0);
                        break;
                    case 2:
                        //可贷款储蓄账户  多态
                        acc = new LoanSavingAccount(id, password, name, personID, email, 0.0, 0);
                        break;
                    case 3:
                        //可贷款信用账户  多态
                        acc = new LoanCreditAccount(id, password, name, personID, email, 0.0, 1500.0, 0L);
                        break;
                    default:
                        /*System.out.println("账号类型不匹配！");
                        break;*/
                        throw new TypeException("账号类型不匹配!");
                }
            } else {
                //System.out.println("开户失败！");
                throw new RegisterException("开户失败");
            }

            //注册
            if (acc != null) {
                boolean flag = dao.insert(acc);
                if (flag) {
                    //System.out.println("注册成功！");
                    JOptionPane.showMessageDialog(null, "注册成功！");
                } else {
                    //System.out.println("注册失败！");
                    throw new RegisterException("注册失败!");
                }
            }
        } else {
            //System.out.println("两次输入的密码不一致");
            //抛出自定义异常
            throw new RegisterException("两次输入的密码不一致");
        }
        return acc;
    }

    /**
     * 登录
     */

    public Account login(Long id, String password) throws LoginException {
        Account acc = null;
        if (id != null && password != null && !id.equals("") && !password.equals("")) {
            //查询
            acc = dao.selectOne(id, password);
        } else {
            //System.out.println("用户ID和密码不能为空");
            throw new LoginException("用户ID和密码不能为空");
        }
        if (acc != null) {
            JOptionPane.showMessageDialog(null, "登录成功！");
        } else {
            //System.out.println("登录失败！");
            throw new LoginException("登录失败");
        }
        return acc;
    }


    /**
     * 存款
     */
    public Account deposit(Long id, double money) throws QueryException {
        Account acc = null;
        if (id != null && !id.equals("")) {
            //查询
            acc = dao.selectOne(id);
            if (acc != null) {

                //存款
                acc.deposit(money);
                dao.update(acc);
            } else {
                //System.out.println("账户ID不存在！");
                throw new QueryException("账户ID不存在！");
            }
        } else {
            //System.out.println("账户ID不能为空！");
            throw new QueryException("账户ID不能为空！");
        }
        return acc;
    }


    /**
     * 取款
     */
    public Account withdraw(Long id, String password, double money) throws QueryException, BalanceNotEnoughException {
        Account acc = null;
        if (id != null && password != null && !id.equals("") && !password.equals("")) {
            acc = dao.selectOne(id, password);
            if (acc != null) {
                //多态
                acc.withdraw(money);
                dao.update(acc);
            } else {
                throw new QueryException("当前账户的ID和密码不匹配");
            }
        } else {
            //System.out.println("当前账户的ID或者密码不能为空");
            throw new QueryException("当前账户的ID或者密码不能为空");
        }
        return acc;
    }

    /**
     * 修改透支额度
     */
    public Account updateCeiling(Long id, String password, double money)
            throws QueryException, TypeException {
        Account acc = null;
        if(id!=null && password!=null && !id.equals("") && !password.equals("")){
            acc = dao.selectOne(id, password);
            if(acc!=null){
                //判断acc是否是信用账户，是才可以设置透支额度
                if(acc instanceof CreditAccount){
                    //setCeiling是子类CreditAccount拓展的方法，必须进行强制转换成CreditAccount类型才可以使用
                    ((CreditAccount) acc).setCeiling(money);
                    dao.update(acc);
                }else{
                    //System.out.println("当前银行卡类型不支持修改透支额度");
                    throw new TypeException("当前银行卡类型不支持修改透支额度");
                }
            }else{
                throw new QueryException("当前账户的ID和密码不匹配");
            }
        }else{
            // System.out.println("当前账户的ID或者密码不能为空");
            throw new QueryException("当前账户的ID或者密码不能为空");
        }
        return acc;
    }


    /**
     * 转账逻辑，较为复杂，需要考虑以下情况：1  账户类型
     * 2   账户钱够不够
     * 3    转入和转出账户
     */
    public boolean transfer(Long from, String passwordForm, Long to, double money) throws QueryException, TransferException, BalanceNotEnoughException {
        if (from != null && passwordForm != null && to != null && !from.equals("") && !passwordForm.equals("") && !to.equals("")) {
            if (from != to) {
                Account accFrom = dao.selectOne(from, passwordForm);
                if (accFrom != null) {
                    Account accTo = dao.selectOne(to);
                    if (accTo != null) {
                        if ((accFrom instanceof SavingAccount) && (accFrom.getBalance() < money)) {
                            // System.out.println("账户钱不够");
                            //  return false;
                            throw new BalanceNotEnoughException("账户金额不够");
                        }
                        if ((accFrom instanceof CreditAccount) && (accFrom.getBalance() + ((CreditAccount) accFrom).getCeiling() < money)) {
//                            System.out.println("账户钱不够");
//                            return false;
                            throw new BalanceNotEnoughException("账户金额不够");
                        }
                        accFrom.withdraw(money);
                        accTo.deposit(money);
                        dao.update(accFrom);
                        dao.update(accTo);
                        System.out.println("转账成功");
                        return true;

                    } else {
                        //System.out.println("转入账户不存在");
                        throw new QueryException("转入账户不存在");
                    }

                } else {
                    //System.out.println("转出账户不存在");
                    throw new QueryException("转出账户不存在");
                }
            } else {
                //System.out.println("转出账户和转入账户不能相同");
                throw new QueryException("转出账户和转入账户不能相同");
            }

        } else {
            //System.out.println("请输入正确信息");
            throw new QueryException("请输入正确信息");
        }


    }

    //贷款
    public Account requestLoan(Long id, double money) throws QueryException, TypeException, LoanException {
        Account acc = null;
        if (id != null && !id.equals("")) {
            acc = dao.selectOne(id);
            if (acc != null) {
                if (acc instanceof Loanable) {
                    ((Loanable) acc).requestLoan(money);
                    dao.update(acc);
                    //return acc;
                } else {
                    //System.out.println("当前账户不支持贷款");
                    throw new TypeException("当前账户不支持贷款");
                }
            }
            // System.out.println("账户不存在");
            throw new QueryException("账户不存在");

        } else {
            //System.out.println("请输入正确信息");
            throw new QueryException("请输入正确信息");
        }

    }

    //还贷款
    public Account payLoan(Long id, double money) throws QueryException, TypeException, LoanException {
        Account acc = null;
        if (id != null && !id.equals("")) {
            acc = dao.selectOne(id);
            if (acc != null) {
                if (acc instanceof Loanable) {
                    ((Loanable) acc).payLoan(money);
                    dao.update(acc);
                } else {
                    //System.out.println("当前账户不支持还款！");
                    throw new TypeException("当前账户类型不支持还款！");
                }
            } else {
                //System.out.println("账户ID不存在！");
                throw new QueryException("账户ID不存在！");
            }
        } else {
            //System.out.println("账户ID不能为空！");
            throw new QueryException("账户ID不能为空！");
        }
        return acc;
    }

   //统计所有账户总额
    public double totalBalance() {
        double sum = 0.0;
        for (Account account : dao.selectAll()) {
            if (account != null) {
                sum += account.getBalance();
            }
        }
        return sum;
    }

    /**
     * 统计账户信用额度，有且仅有信用卡才符合条件
     */
    public double totalCeiling() {
        List<Account> accs = dao.selectAll();
        double total = 0;
        for (Account acc : accs) {
            if (acc instanceof CreditAccount) {
                total += ((CreditAccount) acc).getCeiling();
            }
        }
        return total;
    }

    //统计所有账户贷款的总额
        public double totalLoadAmount() {
            double sum = 0.0;
            for (Account acc : dao.selectAll()) {
                if (acc != null) {
                    if (acc instanceof LoanSavingAccount) {
                        sum += ((LoanSavingAccount) acc).getLoanAmount();
                    }
                    if (acc instanceof LoanCreditAccount) {
                        sum += ((LoanCreditAccount) acc).getLoanAmount();
                    }
                }
            }
            return sum;
        }

        public TreeSet<RankVO> rank() {
            TreeSet<RankVO> set = new TreeSet<>();
            for (Account account : dao.selectAll()) {
                if (account != null) {
                    String personId = account.getPersonId();
                    String name = account.getName();
                    double total = totalBalanceByPersonID(personId);
                    //封装RankVO
                    RankVO rankVO = new RankVO(personId, name, total);
                    set.add(rankVO);
                }
            }
            return set;
        }

        private double totalBalanceByPersonID(String personId) {
            double sum = 0.0;
            for (Account acc : dao.selectAll()) {
                if(acc!=null && acc.getPersonId().equals(personId)){
                    sum+=acc.getBalance();
                }
            }
            return sum;
        }

    private List<Account> accounts;
    private static final String FILE_NAME = "accounts.ser";


    }








